package hibernate;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;

public class JdbcDAO implements IJdbcDAO{
	
	private JdbcTemplate jdbcTemplate;
	
	public Page findPageBySQL(final String sql, final Object[] args, final int start, final int limit) {
		
		List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();

		String countSQL = "select count(*) " + removeSelect(removeOrders(sql));
		Long count = jdbcTemplate.queryForLong(countSQL, args);

		if (count < 1)
			return new Page(start, limit, Integer.parseInt(String
					.valueOf(count)), new ArrayList());

		data = jdbcTemplate.query(new PreparedStatementCreator() {
			public PreparedStatement createPreparedStatement(Connection arg0)
					throws SQLException {
				PreparedStatement pstmt = arg0.prepareStatement(sql);
				if (args != null) {
					for (int i = 0; i < args.length; ++i)
						pstmt.setObject(i + 1, args[i]);
				}

				if (limit > 0)
					pstmt.setMaxRows(limit + start);

				return pstmt;
			}

		}, new DefaultRowMapper(start, limit));

		return new Page(start, limit, Integer.parseInt(String.valueOf(count)),
				data);
	}
	
	
	private static String removeSelect(String hql) {
		int beginPos = hql.toLowerCase().indexOf("from");
		return hql.substring(beginPos);
	}

	private static String removeOrders(String hql) {
		Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*",
				Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(hql);
		StringBuffer sb = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(sb, "");
		}
		m.appendTail(sb);
		return sb.toString();
	}


	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}


	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

}
